namespace FIREFLYX {

    /** 输出画面分辨率自适应模式 */
    export enum ResolutionAdaptationMode {
        /** 按实际拉伸 */
        REALITY,
        /** 固定分辨宽，高度自适应 */
        FIXED_WIDTH,
        /** 固定分辨高，高度自适应*/
        FIXED_HEIGHT
    }

    /** 画面方向旋转模式 */
    export enum AspectRotateMode {
        /** 不做旋转操作 */
        NONE,
        /** 旋转保持竖方向（高度 大于 宽度） */
        PORTRAIT,
        /** 旋转保持横方向（宽度 大于 高度） */
        LANDSCAPE
    }

    /**
     * 画面方位朝向 管理器
     */
    export class ViewAspectManager {
        private static _externalDIV: Nullable<HTMLDivElement>;  //外部输入的html div 容器

        private static _inited = false;
        private static _fixedResolution: number = 1080;
        private static _resolutionAdapMode: ResolutionAdaptationMode = ResolutionAdaptationMode.REALITY;
        private static _aspectRotateMode: AspectRotateMode = AspectRotateMode.NONE;
        private static _useDevicePixelRatioFix: boolean = true;
        private static _lastWidth = 0;
        private static _lastHeight = 0;
        private static _canvasRotation: 0 | 90 | -90 = 0;

        /** 自动在每次updata 检查 分辨率自适应 和 方向 */
        public static autoRefresh = true;

        /** 输出画面分辨率自适应模式 */
        public static get resolutionAdapMode() { return this._resolutionAdapMode; }
        public static set resolutionAdapMode(val) {
            if (this._resolutionAdapMode == val) return;
            this._resolutionAdapMode = val;
            this.resolutionAdaptation();
        }
        /** 输出画面方向的旋转模式 */
        public static get aspectRotateMode() { return this._aspectRotateMode; }
        public static set aspectRotateMode(val) {
            if (this._aspectRotateMode == val) return;
            this._aspectRotateMode = val;
            this.aspectRotateAdaptation();
            this.resolutionAdaptation();
        }
        /** 使用设备像素比率修正分辨率 */
        public static get useDevicePixelRatioFix() { return this._useDevicePixelRatioFix; }
        public static set useDevicePixelRatioFix(val) {
            if (this._useDevicePixelRatioFix == val) return;
            this._useDevicePixelRatioFix = val;
            this.resolutionAdaptation();
        }
        /** 固定分辨率设定值 */
        public static get fixedResolution() { return this._fixedResolution; }
        public static set fixedResolution(val) {
            const tarVal = isNaN(val) || val < 1 ? 1 : val;
            if (this._fixedResolution == tarVal) return;
            this._fixedResolution = tarVal;
            if (this._resolutionAdapMode == ResolutionAdaptationMode.FIXED_WIDTH ||
                this._resolutionAdapMode == ResolutionAdaptationMode.FIXED_HEIGHT) {
                this.resolutionAdaptation();
            }
        }

        /** html canvas 对象 */
        public static canvasElement: HTMLCanvasElement;

        /** 初始化 */
        public static init(element: HTMLCanvasElement | HTMLDivElement) {
            if (this._inited) return;
            if (!element) {
                console.error(`element is null.`);
                return;
            }
            //
            let canvasEle: Nullable<HTMLCanvasElement> = null;
            if (element instanceof HTMLCanvasElement) {
                canvasEle = element;
            } else {
                this._externalDIV = element;
                this._externalDIV;
                //是一个DIV ，自己创建一个 canvas 元素
            }

            this.canvasElement = canvasEle as HTMLCanvasElement;

            //end
            this._inited = true;
        }

        /** 更新 */
        public static update() {
            //
            if (this.autoRefresh) {
                this.checkContainerResize();
            }
        }

        /** 执行分辨自适应调整 */
        public static resolutionAdaptation() {
            const canvas = this.canvasElement;
            const parent = canvas.parentElement;
            if (!parent) return;
            const whReverse = this._canvasRotation != 0;
            let w = whReverse ? parent.clientHeight : parent.clientWidth;
            let h = whReverse ? parent.clientWidth : parent.clientHeight;

            //style clientSize 、top 、 left同步
            let top = 0;
            let left = 0;
            let defHalf = Math.abs(w - h) * 0.5;
            switch (this._canvasRotation) {
                case 90:
                    top = defHalf;
                    left = -defHalf;
                    break;
                case -90:
                    top = -defHalf;
                    left = defHalf;
                    break;
                default:
            }
            //style
            canvas.style.position = "absolute";
            canvas.style.width = `${w}px`;
            canvas.style.height = `${h}px`;
            canvas.style.top = `${top}px`;
            canvas.style.left = `${left}px`;

            let fixPixelRatio = !this._useDevicePixelRatioFix ? 1 : devicePixelRatio || 1;
            const maxW = w * fixPixelRatio;
            const maxH = h * fixPixelRatio;

            //调整 canvas画布实际分辨率尺寸
            //canvas.width 和 canvas.height 是实际分辨率
            //canvas.clientWidth、canvas.clientHeight 为 html元素 尺寸
            switch (this._resolutionAdapMode) {
                case ResolutionAdaptationMode.REALITY:
                    canvas.width = maxW;
                    canvas.height = maxH;
                    break;
                case ResolutionAdaptationMode.FIXED_WIDTH:
                    canvas.width = this._fixedResolution > maxW ? maxW : this._fixedResolution;
                    canvas.height = canvas.width * (h / w);
                    break;
                case ResolutionAdaptationMode.FIXED_HEIGHT:
                    canvas.height = this._fixedResolution > maxH ? maxH : this._fixedResolution;
                    canvas.width = canvas.height * (w / h);
                    break;
                default:
            }

            //抛事件
            GlobalEventManager.Instance.dispatchEvent("viweFrameChange", "resize");
            this._lastWidth = w;
            this._lastHeight = h;
        }

        /** 执行画面方向调整 */
        public static aspectRotateAdaptation() {
            const canvas = this.canvasElement;
            const parent = canvas.parentElement;
            if (!parent) return;
            //计算旋转
            let tarRotate = this.calcAspectRotation();
            if (tarRotate == this._aspectRotateMode) return;
            //调整 css style ，让canvas旋转
            canvas.style.transform = `rotate(${tarRotate}deg)`;

            this._canvasRotation = tarRotate as any;
        }

        /** 计算方向旋转角度 */
        private static calcAspectRotation() {
            const canvas = this.canvasElement;
            const parent = canvas.parentElement;
            if (!parent) return 0;
            let tarRotate = 0;
            //判断是否需要 旋转操作
            switch (this._aspectRotateMode) {
                case AspectRotateMode.NONE: tarRotate = 0; break;
                case AspectRotateMode.LANDSCAPE: tarRotate = parent.clientHeight > parent.clientWidth ? 90 : 0; break;
                case AspectRotateMode.PORTRAIT: tarRotate = parent.clientWidth > parent.clientHeight ? -90 : 0; break;
                default:
            }

            return tarRotate;
        }

        /** 检查容器尺寸变化 */
        private static checkContainerResize() {
            const canvas = this.canvasElement;
            const parent = canvas.parentElement;
            if (!parent) return;
            const whReverse = this._canvasRotation != 0;
            let w = whReverse ? parent.clientHeight : parent.clientWidth;
            let h = whReverse ? parent.clientWidth : parent.clientHeight;
            //方向旋转 自适应
            this.aspectRotateAdaptation();
            //检查是否 有变化
            let isSizeDirty = this._lastWidth != w || this._lastHeight != h;
            if (!isSizeDirty) return;
            this.resolutionAdaptation();
        }
    }
}